/*
 * @brief:
 * @Author: TzzzT
 * @Date: 2022-05-08 21:37:01
 * @LastEditTime: 2023-05-02 19:01:34
 * @LastEditors: TzzzT
 */

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "mfrc522.h"
#include "spi.h"
#include <stdio.h>
#include <string.h>

#include "RCS_nfc.h"
#include "RCS_master.h"
#include "RCS_net.h"
#include "bc260.h"
#include "RCS_protocol.h"
#include "RCS_ble_master.h"

static const char *NFC_TAG = "NFC_TAG";

extern QueueHandle_t xGameQueue;
extern rcs_mast_system_t rcsSystem;
esp_err_t nfc_init(void)
{
    // 先初始化spi引脚
    esp_err_t ret = ESP_FAIL;
    ret = spi_init(PIN_NUM_CLK, PIN_NUM_MOSI, PIN_NUM_MISO);
    if (ret != ESP_OK)
    {
        return ret;
    }

    // 配置寄存器，开启天线
    MFRC522_Pin_Init(PIN_NUM_RST, PIN_NUM_CS);
    ret = MFRC522_Start();
    return ret;
}

void open_rc522(void)
{
    MFRC522_Start();
}

static void analyse_command(uint8_t *block)
{
    if (block[1] != 0)
    {
        block[1]--;
        uint8_t prop = block[0];
        uint8_t command = 0;
        switch (prop)
        {
        case NFC_INCREASE_DAMAGE:
            command = INCREASE_DAMAGE_COMM;
            break;
        case NFC_INCREASE_HP:
            command = INCREASE_HP_COMM;
            break;
        case NFC_REBORN:
            command = REBORN_P_STA_COMM;
            break;
        case NFC_INCREASE_BULLET_NUM:
            command = INCREASE_BULLET_COMM;
            break;
        default:
        {
            uint32_t param_arr[2] = {0};
            param_arr[0] = NFC_UNKNOWN;
            param_arr[1] = prop;
            size_t message_length;
            char *message = make_net_json_package(ERROR_NET_UP, &message_length, param_arr);
            if (message)
            {
                bc_send_package_to_server(message, message_length);
                free(message);
            }
            break;
        }
        }
        uint8_t *package = make_prop_command_package(command, rcsSystem.equip.core.battery);
        ESP_LOGI(NFC_TAG, "put nfc_command_package in queue");
        if (xQueueSend(xGameQueue, package, pdMS_TO_TICKS(200)) != pdPASS)
        {
            ESP_LOGE(NFC_TAG, "queue full.");
        }
        free(package);
    }
}

void detect_tag(void)
{
    uint8_t ret = 0xff;
    uint8_t tag_type[2] = {0};
    uint8_t tag_seri[4] = {0};
    uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    uint8_t block_data[16] = {0};
    uint8_t class_type = 0;
    char strprt[50] = {0};
    ret = MFRC522_Request(PICC_REQIDL, tag_type);
    if (ret != MI_OK)
    {
        return;
    }
    // ESP_LOGI(NFC_TAG, "get Tag type:%02x%02x.", tag_type[0], tag_type[1]);
    if (MFRC522_Anticoll(tag_seri) != MI_OK)
    {
        return;
    }
    sprintf(strprt, "The Card ID is: %02X%02X%02X%02X", tag_seri[0], tag_seri[1], tag_seri[2], tag_seri[3]);
    // printf ("%s\r\n",strprt);
    ret = MFRC522_SelectTag(tag_seri);
    // ESP_LOGI(NFC_TAG, "SelectTag size:%d", ret);
    ret = MFRC522_Auth(PICC_AUTHENT1A, DATA_CLASS_BLOCK_NUM, key, tag_seri); // 选择扇区
    ret = MFRC522_Read(DATA_CLASS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "read error");
        return;
    }
    class_type = block_data[0];
    ESP_LOGI(NFC_TAG, "read success, data class:%02x", class_type);
    memset(block_data, 0, 16);

    switch (class_type)
    {
    case PROPS_CLASS:
    {
        set_game_event(REMOTE_COMM_EVENT, 4);
        ret = MFRC522_Auth(PICC_AUTHENT1A, DATA_CLASS_BLOCK_NUM, key, tag_seri); // 选择扇区
        ret = MFRC522_Read(DATA_CLASS_BLOCK_NUM, block_data);
        if (ret != MI_OK)
        {
            ESP_LOGE(NFC_TAG, "read error");
            return;
        }
        analyse_command(block_data);
        ret = MFRC522_Write(PROPS_BLOCK_NUM, block_data);
        if (ret != MI_OK)
        {
            ESP_LOGE(NFC_TAG, "write error");
            return;
        }
        ESP_LOGI(NFC_TAG, "write success:%02x %02x", block_data[0], block_data[1]);
        break;
    }
    case BDA_ARMOR_CLASS:
    {
        ret = MFRC522_Auth(PICC_AUTHENT1A, BDA1_BLOCK_NUM, key, tag_seri); // 选择扇区
        ret = MFRC522_Read(BDA1_BLOCK_NUM, block_data);
        if (ret != MI_OK)
        {
            ESP_LOGE(NFC_TAG, "read error");
            return;
        }
        ESP_LOGI(NFC_TAG, "read armor bda success: ");
        esp_log_buffer_hex(NFC_TAG, block_data, 6);
        break;
    }
    case BDA_GUN_POI_CLASS:
    {
        ret = MFRC522_Auth(PICC_AUTHENT1A, BDA1_BLOCK_NUM, key, tag_seri); // 选择扇区
        ret = MFRC522_Read(BDA1_BLOCK_NUM, block_data);
        if (ret != MI_OK)
        {
            ESP_LOGE(NFC_TAG, "read error");
            return;
        }
        ESP_LOGI(NFC_TAG, "read gun poi bda success: ");
        esp_log_buffer_hex(NFC_TAG, block_data, 6);
        break;
    }
    case BDA_GUN_POI_SCR_CLASS:
    {
        ret = MFRC522_Auth(PICC_AUTHENT1A, BDA1_BLOCK_NUM, key, tag_seri); // 选择扇区
        ret = MFRC522_Read(BDA1_BLOCK_NUM, block_data);
        if (ret != MI_OK)
        {
            ESP_LOGE(NFC_TAG, "read error");
            return;
        }
        ESP_LOGI(NFC_TAG, "read gun scr bda success: ");
        esp_log_buffer_hex(NFC_TAG, block_data, 6);
        break;
    }
    default:
        break;
    }
}

void close_rc522(void)
{
    MFRC522_Reset();
}

void test_add_increase_damage_tag(void)
{
    uint8_t ret = 0xff;
    uint8_t tag_type[2] = {0};
    uint8_t tag_seri[4] = {0};
    uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    uint8_t block_data[16] = {0};
    char strprt[50] = {0};
    ret = MFRC522_Request(PICC_REQIDL, tag_type);
    if (ret != MI_OK)
    {
        return;
        // ret = MFRC522_Request(PICC_REQALL, tag_id);
    }
    ESP_LOGI(NFC_TAG, "get Tag type:%02x%02x.", tag_type[0], tag_type[1]);
    if (MFRC522_Anticoll(tag_seri) != MI_OK)
    {
        return;
    }
    sprintf(strprt, "The Card ID is: %02X%02X%02X%02X", tag_seri[0], tag_seri[1], tag_seri[2], tag_seri[3]);
    printf("%s\r\n", strprt);
    ret = MFRC522_SelectTag(tag_seri);
    ESP_LOGI(NFC_TAG, "SelectTag size:%d", ret);
    ret = MFRC522_Auth(PICC_AUTHENT1A, PROPS_BLOCK_NUM, key, tag_seri); // 选择扇区
    ret = MFRC522_Read(PROPS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "read error");
        return;
    }
    ESP_LOGI(NFC_TAG, "read success:%02x %02x", block_data[0], block_data[1]);
    block_data[0] = 0;
    block_data[1] += 10;
    ret = MFRC522_Write(PROPS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "write error");
        return;
    }
    ESP_LOGI(NFC_TAG, "write success:%02x %02x", block_data[0], block_data[1]);
}

void test_add_increase_hp_tag(void)
{
    uint8_t ret = 0xff;
    uint8_t tag_type[2] = {0};
    uint8_t tag_seri[4] = {0};
    uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    uint8_t block_data[16] = {0};
    char strprt[50] = {0};
    ret = MFRC522_Request(PICC_REQIDL, tag_type);
    if (ret != MI_OK)
    {
        return;
        // ret = MFRC522_Request(PICC_REQALL, tag_id);
    }
    ESP_LOGI(NFC_TAG, "get Tag type:%02x%02x.", tag_type[0], tag_type[1]);
    if (MFRC522_Anticoll(tag_seri) != MI_OK)
    {
        return;
    }
    sprintf(strprt, "The Card ID is: %02X%02X%02X%02X", tag_seri[0], tag_seri[1], tag_seri[2], tag_seri[3]);
    printf("%s\r\n", strprt);
    ret = MFRC522_SelectTag(tag_seri);
    ESP_LOGI(NFC_TAG, "SelectTag size:%d", ret);
    ret = MFRC522_Auth(PICC_AUTHENT1A, PROPS_BLOCK_NUM, key, tag_seri); // 选择扇区
    ret = MFRC522_Read(PROPS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "read error");
        return;
    }
    ESP_LOGI(NFC_TAG, "read success:%02x %02x", block_data[0], block_data[1]);
    block_data[0] = 1;
    block_data[1] += 10;
    ret = MFRC522_Write(PROPS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "write error");
        return;
    }
    ESP_LOGI(NFC_TAG, "write success:%02x %02x", block_data[0], block_data[1]);
}

void test_add_reborn_tag(void)
{
    uint8_t ret = 0xff;
    uint8_t tag_type[2] = {0};
    uint8_t tag_seri[4] = {0};
    uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    uint8_t block_data[16] = {0};
    char strprt[50] = {0};
    ret = MFRC522_Request(PICC_REQIDL, tag_type);
    if (ret != MI_OK)
    {
        return;
        // ret = MFRC522_Request(PICC_REQALL, tag_id);
    }
    ESP_LOGI(NFC_TAG, "get Tag type:%02x%02x.", tag_type[0], tag_type[1]);
    if (MFRC522_Anticoll(tag_seri) != MI_OK)
    {
        return;
    }
    sprintf(strprt, "The Card ID is: %02X%02X%02X%02X", tag_seri[0], tag_seri[1], tag_seri[2], tag_seri[3]);
    printf("%s\r\n", strprt);
    ret = MFRC522_SelectTag(tag_seri);
    ESP_LOGI(NFC_TAG, "SelectTag size:%d", ret);
    ret = MFRC522_Auth(PICC_AUTHENT1A, PROPS_BLOCK_NUM, key, tag_seri); // 选择扇区
    ret = MFRC522_Read(PROPS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "read error");
        return;
    }
    ESP_LOGI(NFC_TAG, "read success:%02x %02x", block_data[0], block_data[1]);
    block_data[0] = 2;
    block_data[1] += 10;
    ret = MFRC522_Write(PROPS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "write error");
        return;
    }
    ESP_LOGI(NFC_TAG, "write success:%02x %02x", block_data[0], block_data[1]);
}

void test_add_increase_bulletnum_tag(void)
{
    uint8_t ret = 0xff;
    uint8_t tag_type[2] = {0};
    uint8_t tag_seri[4] = {0};
    uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    uint8_t block_data[16] = {0};
    char strprt[50] = {0};
    ret = MFRC522_Request(PICC_REQIDL, tag_type);
    if (ret != MI_OK)
    {
        return;
        // ret = MFRC522_Request(PICC_REQALL, tag_id);
    }
    ESP_LOGI(NFC_TAG, "get Tag type:%02x%02x.", tag_type[0], tag_type[1]);
    if (MFRC522_Anticoll(tag_seri) != MI_OK)
    {
        return;
    }
    sprintf(strprt, "The Card ID is: %02X%02X%02X%02X", tag_seri[0], tag_seri[1], tag_seri[2], tag_seri[3]);
    printf("%s\r\n", strprt);
    ret = MFRC522_SelectTag(tag_seri);
    ESP_LOGI(NFC_TAG, "SelectTag size:%d", ret);
    ret = MFRC522_Auth(PICC_AUTHENT1A, PROPS_BLOCK_NUM, key, tag_seri); // 选择扇区
    ret = MFRC522_Read(PROPS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "read error");
        return;
    }
    ESP_LOGI(NFC_TAG, "read success:%02x %02x", block_data[0], block_data[1]);
    block_data[0] = 3;
    block_data[1] += 10;
    ret = MFRC522_Write(PROPS_BLOCK_NUM, block_data);
    if (ret != MI_OK)
    {
        ESP_LOGE(NFC_TAG, "write error");
        return;
    }
    ESP_LOGI(NFC_TAG, "write success:%02x %02x", block_data[0], block_data[1]);
}
